<template>
  <div class="container">
    <h3>菜单管理</h3>
    <div>
      <div>
        <el-button type="success" size="mini" @click="addNodeDialog()">
          添加
        </el-button>
      </div>
      <div style="margin-top: 10px">
        <el-table
          :data="tableData"
          style="width: 100%; margin-bottom: 20px"
          row-key="id"
          border
          :tree-props="{ children: 'children' }"
          :expand-row-keys="expandRowKeys"
        >
          <el-table-column prop="name" label="菜单名称" />
          <el-table-column label="图标" width="50">
            <template slot-scope="scope">
              <i :class="scope.row.icon" />
            </template>
          </el-table-column>
          <el-table-column prop="perms" label="权限标识" />
          <el-table-column prop="path" label="路由地址" />
          <el-table-column prop="component" label="组件路径" />
          <el-table-column prop="sortValue" width="60px" label="排序" />
          <el-table-column label="类型" width="60px">
            <template slot-scope="scope">
              {{ getTypeLabel(scope.row.type) }}
            </template>
          </el-table-column>
          <el-table-column prop="status" label="状态" width="70px">
            <template slot-scope="scope">
              <el-switch
                :value="scope.row.status"
                :active-value="1"
                :inactive-value="0"
                @change="(v) => changeStatus(scope.row.id, v)"
              />
            </template>
          </el-table-column>
          <el-table-column fixed="right" label="操作" width="200">
            <template slot-scope="scope">
              <el-button
                type="success"
                size="mini"
                :disabled="scope.row.type === 2"
                @click="addNodeDialog(scope.row)"
              >
                <i class="el-icon-plus" style="color: white" />
              </el-button>
              <el-button
                type="primary"
                size="mini"
                style="margin-right: 10px"
                @click="editNodeDialog(scope.row)"
              >
                <i class="el-icon-edit" style="color: white" />
              </el-button>
              <DeleteBtn
                :disabled="scope.row.children && scope.row.children.length > 0"
                size="mini"
                @deleteItem="removeMenu(scope.row.id)"
              />
            </template>
          </el-table-column>
        </el-table>
      </div>
    </div>
    <el-dialog
      :title="nodeDialogType === 'add' ? '添加节点' : '编辑节点'"
      :visible="nodeDialogVisible"
      width="600px"
      @close="closeNodeDialog()"
    >
      <el-form :model="currentNode" label-width="80px">
        <el-form-item label="上级部门">
          <el-input
            :value="currentNode.parentName"
            size="small"
            :disabled="true"
          />
        </el-form-item>
        <el-form-item label="菜单类型">
          <el-radio-group v-model="currentNode.type">
            <el-radio :label="0">目录</el-radio>
            <el-radio :label="1">菜单</el-radio>
            <el-radio :label="2">按钮</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="菜单名称">
          <el-input v-model="currentNode.name" size="small" />
        </el-form-item>
        <el-form-item label="图标" size="small">
          <!-- <el-input v-model="currentNode.icon" size="small" /> -->
          <el-popover placement="bottom" width="400" trigger="click">
            <el-button slot="reference">
              <i :class="currentNode.icon" style="font-size: 18px" />
            </el-button>
            <div>
              <i
                v-for="iconName of elIconNames"
                :key="iconName"
                :class="iconName"
                class="icon-item"
                @click="changeIcon(iconName)"
              />
            </div>
          </el-popover>
        </el-form-item>
        <el-form-item label="排序">
          <el-input-number v-model="currentNode.sortValue" size="small" />
        </el-form-item>
        <el-form-item label="路由地址">
          <el-input v-model="currentNode.path" size="small" />
        </el-form-item>
        <el-form-item label="组件路径">
          <el-input v-model="currentNode.component" size="small" />
        </el-form-item>
        <el-form-item label="权限标识">
          <el-input v-model="currentNode.perms" size="small" />
        </el-form-item>
        <el-form-item label="状态">
          <!-- <el-input :value="currentNode.status" size="small" /> -->
          <el-switch
            v-model="currentNode.status"
            :active-value="1"
            :inactive-value="0"
          />
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button size="small" @click="closeNodeDialog()">取 消</el-button>
        <el-button
          size="small"
          type="primary"
          @click="nodeDialogConfirmHandler()"
        >
          确 定
        </el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
import { findNodes, save, removeById, update } from "@/api/system/menu";
import { elIconNames } from "@/utils/el-icon-names";
import DeleteBtn from "@/components/tools/DeleteBtn";

export default {
  components: {
    DeleteBtn,
  },
  data() {
    return {
      tableData: [],
      nodeDialogVisible: false,
      nodeDialogType: "",
      currentNode: {},
      elIconNames,
      expandRowKeys: [],
    };
  },
  async created() {
    await this.fetchData();
    this.expandRowKeys = this.tableData.map((e) => e.id);
  },
  methods: {
    async fetchData() {
      const res = await findNodes();
      this.tableData = res.data;
    },
    getTypeLabel(menuType) {
      const menuTypeLabelDict = ["目录", "菜单", "按钮"];
      return menuTypeLabelDict[menuType];
    },
    addNodeDialog(parentNode) {
      this.nodeDialogVisible = true;
      this.nodeDialogType = "add";
      this.currentNode = {
        parentId: parentNode?.id ?? 0,
        parentName: parentNode?.name,
        icon: "el-icon-discover",
        sortValue: 1,
        status: 1,
      };
      if (!parentNode) this.currentNode.type = 0;
      else if (parentNode.type === 0) this.currentNode.type = 1;
      else if (parentNode.type === 1) {
        this.currentNode.type = 2;
        delete this.currentNode.icon;
      }
    },
    editNodeDialog(currentNode) {
      this.nodeDialogVisible = true;
      this.nodeDialogType = "edit";
      this.currentNode = {
        id: currentNode.id,
        type: currentNode.type,
        name: currentNode.name,
        icon: currentNode.icon,
        sortValue: currentNode.sortValue,
        path: currentNode.path,
        component: currentNode.component,
        perms: currentNode.perms,
        status: currentNode.status,
      };
      this.currentNode.parentName = this.getParent(this.tableData)?.name;
    },
    closeNodeDialog() {
      this.nodeDialogVisible = false;
    },
    changeIcon(iconName) {
      // console.log("iconName =", iconName);
      this.currentNode.icon = iconName;
    },
    async removeMenu(id) {
      await removeById(id);
      await this.fetchData();
    },
    async nodeDialogConfirmHandler() {
      if (this.nodeDialogType === "add") {
        await save(this.currentNode);
      } else if (this.nodeDialogType === "edit") {
        await update(this.currentNode);
      }
      this.fetchData();
      this.closeNodeDialog();
    },
    async changeStatus(id, status) {
      await update({ id, status });
      this.fetchData();
    },
    getParent(nodes) {
      const helper = (node) => {
        if (!node) return null;
        for (const child of node.children || []) {
          if (child.name === this.currentNode.name) {
            return node;
          }
          const subResult = helper(child);
          if (subResult) return subResult;
        }
        return null;
      };
      for (const node of nodes) {
        const result = helper(node);
        if (result) return result;
      }
      return null;
    },
  },
};
</script>

<style scoped>
.container {
  padding: 5px 10px;
}
.icon-item {
  cursor: pointer;
  margin: 3px;
  font-size: 16px;
}
.icon-item:hover {
  background-color: #00bfff80;
}
</style>
